package com.gitee.wsl.flowing.sink

import kotlinx.io.IOException

interface System<B,V>{
    /**
     * Returns a source that reads the bytes of [file] from beginning to end.
     *
     * @throws IOException if [file] does not exist, is not a file, or cannot be read. A file cannot
     *     be read if the current process doesn't have access to [file], if there's a loop of symbolic
     *     links, or if any name is too long.
     */
    @Throws(IOException::class)
     fun source(file: B): Source<V>

    /**
     * Creates a source to read [file], executes [readerAction] to read it, and then closes the
     * source. This is a compact way to read the contents of a file.
     */
    @Throws(IOException::class)
     fun <T> read(file: B, readerAction: Source<V>.() -> T): T

    /**
     * Returns a sink that writes bytes to [file] from beginning to end. If [file] already exists it
     * will be replaced with the new data.
     *
     * @param mustCreate true to throw an [IOException] instead of overwriting an existing file.
     *     This is equivalent to `O_EXCL` on POSIX and `CREATE_NEW` on Windows.
     *
     * @throws IOException if [file] cannot be written. A file cannot be written if its enclosing
     *     directory does not exist, if the current process doesn't have access to [file], if there's
     *     a loop of symbolic links, or if any name is too long.
     */
    @Throws(IOException::class)
     fun sink(file: B, mustCreate: Boolean = false): Sink<V>

    /**
     * Creates a sink to write [file], executes [writerAction] to write it, and then closes the sink.
     * This is a compact way to write a file.
     *
     * @param mustCreate true to throw an [IOException] instead of overwriting an existing file.
     *     This is equivalent to `O_EXCL` on POSIX and `CREATE_NEW` on Windows.
     */
    @Throws(IOException::class)
     fun <T> write(
        file: B,
        mustCreate: Boolean = false,
        writerAction: Sink<V>.() -> T,
    ): T

    /**
     * Returns a sink that appends bytes to the end of [file], creating it if it doesn't already
     * exist.
     *
     * @param mustExist true to throw an [IOException] instead of creating a new file. This is
     *     equivalent to `r+` on POSIX and `OPEN_EXISTING` on Windows.
     *
     * @throws IOException if [file] cannot be written. A file cannot be written if its enclosing
     *     directory does not exist, if the current process doesn't have access to [file], if there's
     *     a loop of symbolic links, or if any name is too long.
     */
    @Throws(IOException::class)
     fun appendingSink(file: B, mustExist: Boolean = false): Sink<V>

}